/* 
    <provides OS-like functionality using a time-triggered scheduler>
    Copyright (C) <2012>  <Jonathan D. Armstrong> <jonathan.armstrong AT mavs.uta.edu>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

#include "projectdefs.h"
#include "nortos.h"

/* 
    timer interrupt
   - provides tick update for scheduler
   - consider tickless interrupt implementation
      to give better power performance for sleep
      heavy applications? -- jda
*/
void timer_interrupt(int sig)
{
    bool ok;
    /* index variable */
    uint8_t i;
    
    #ifdef INTERRUPT_DEBUG
        printf("timer_interrupt()\r\n");
    #endif

    /* loop through all tasks */
    for (i = 0; i < MAX_TASKS; i++)
    {
        ok = true;
        ok &= (tasks[i].state == DELAYED);
        ok &= (tasks[i].delay > 0);
        
        /* task delayed? */
        if (ok)
        {
            /* decrement remaining tick count */
            tasks[i].delay--;
            
            /* tick count finally zero? */
            if (tasks[i].delay == 0)
            {
                /* set task as ready to run */
                tasks[i].state = READY;
                
                #ifdef INTERRUPT_DEBUG
                    printf("tasks[%u].state = %u\r\n", i, tasks[i].state);
                #endif
            }
        }
    }
    
    /* re-enable signal handler - specific to PC port */
    signal(sig, timer_interrupt);
    alarm(1);
}